package aufgabe5;

public class Rekurison {

	public static void main(String[] args) {
		/*
		 * n: 0 1 2 3 4 5 6 7 8 9 val: 1 1 1 6 11 26 66 151 361 861
		 */
		int erg = 0;
		int n = 0;
		int[] speicherR = new int[27];
		int[] speicherI = new int[27];
		int[] speicherR2 = new int[27];
		// n=26 ist der letzte Wert, bevor es ueberlaeuft
		int[] referenzen = new int[27];
		referenzen = funkRMZ(26, referenzen);
		while (erg < Integer.MAX_VALUE / 2) {
			erg = funkR(n);
			speicherR[n] = erg;
			speicherI[n] = funkI(n);
			speicherR2[n] = funkR2(n);
			n++;
		}
		for (int i = 0; i < 27; i++) {
			System.out.print("funkR(" + i + "): " + speicherR[i] + "\n");
			System.out.print("funkRMZ(26): n: " + i + " = " + referenzen[i]
					+ "\n");
			System.out.print("funkI(" + i + "): " + speicherI[i] + "\n");
			System.out.print("funkR2(" + i + "): " + speicherR2[i] + "\n");
		}
	}

	/**
	 * Summiert eine dreier Zahlenfolge von 0 bis n
	 * 
	 * @param n
	 *            liniare Anzahl zur Berechnung
	 * 
	 * @return Die berechnete Summe
	 */
	public static int funkR(int n) {
		if (n < 3) {
			return 1;
		} else {
			return funkR(n - 1) + 2 * funkR(n - 2) + 3 * funkR(n - 3);
		}
	}

	/**
	 * Zaehlt die Methoden-Aufrufe
	 * 
	 * @param n
	 *            liniare Anzahl zur Berechnung
	 * 
	 * @return Array der Aufrufe bei n
	 */
	public static int[] funkRMZ(int n, int[] referenzen) {
		referenzen[n] += 1;
		if (n < 3) {
		} else {
			referenzen = funkRMZ(n - 1, referenzen);
			referenzen = funkRMZ(n - 2, referenzen);
			referenzen = funkRMZ(n - 3, referenzen);
		}
		return referenzen;
	}

	/**
	 * Summiert eine dreier Zahlenfolge von 0 bis n
	 * 
	 * @param n
	 *            liniare Anzahl zur Berechnung
	 * 
	 * @return Die berechnete Summe
	 */
	public static int funkI(int n) {
		if (n < 3) {
			return 1;
		} else {
			int val1 = 1;
			int val2 = 1;
			int val3 = 1;
			for (int i = n; i >= 3; i--) {
				int temp = val3;
				val3 = val1 * 3 + val2 * 2 + val3;
				val1 = val2;
				val2 = temp;
			}
			return val3;
		}
	}

	/**
	 * Summiert eine dreier Zahlenfolge von 0 bis n
	 * 
	 * @param n
	 *            liniare Anzahl zur Berechnung
	 * 
	 * @return Die berechnete Summe
	 */
	public static int funkR2(int n) {
		if (n < 3) {
			return 1;
		} else {
			return funkR2Help(n, 1, 1, 1);
		}
	}

	/**
	 * Summiert eine dreier Zahlenfolge von 0 bis n
	 * 
	 * @param n
	 *            liniare Anzahl zur Berechnung
	 * @param val1
	 *            Wert vor n-3
	 * @param val2
	 *            Wert vor n-2
	 * @param val3
	 *            Wert vor n-1
	 * @return Die berechnete Summe
	 */
	public static int funkR2Help(int n, int val1, int val2, int val3) {
		if (n < 3) {
			return val3;
		} else {
			return funkR2Help(n - 1, val2, val3, val1 * 3 + val2 * 2 + val3);
		}
	}

}
